<?php declare(strict_types=1);
/**
 * This file is part of Swoft.
 *
 * @link https://swoft.org
 * @document https://swoft.org/docs
 * @contact group@swoft.org
 * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE
 */

namespace App\Http\Middleware;

use App\Exception\PermissionException;
use App\Http\Lib\Service;
use App\Http\Lib\ServiceInfo;
use App\Lib\RpcClient\RpcClient;
use App\Lib\RpcClient\RpcResult;
use App\Lib\RpcRequest\RpcRequest;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Bean\BeanFactory;
use Swoft\Http\Message\Request;
use Swoft\Http\Server\Contract\MiddlewareInterface;
use App\Rpc\Model\Logic\PermissionLogic;
use function context;

/**
 * Class PermissionMiddleware - Custom middleware
 * @Bean("PermissionMiddleware")
 * @package App\Http\Middleware
 */
class PermissionMiddleware implements MiddlewareInterface
{
    /**
     * Process an incoming server request.
     *
     * @param ServerRequestInterface|Request $request
     * @param RequestHandlerInterface $handler
     *
     * @return ResponseInterface
     * @throws \Swoft\Consul\Exception\ClientException
     * @throws \Swoft\Consul\Exception\ServerException
     * @throws PermissionException
     * @inheritdoc
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        /** @var ServiceInfo $serviceInfo */
        $serviceInfo = $request->getAttribute('serviceInfo');
        $action = $serviceInfo->getAction();

        $actionPermission = config('service.'.strtolower($serviceInfo->getServiceName()).'_permission', []);
        $actionPermission = $actionPermission?json_decode($actionPermission, true):[];

        //@1层层解析，会先走serviceName 然后再去判断server, 这里需要判断是否是多维度得
        $validate_actions = config('service.'.strtolower($serviceInfo->getServiceName()).'_validate_actions', '');
        if($validate_actions){
            if(!is_json($validate_actions)){
                //代表是 一维数组，只有一个lib
                $condition = !empty($actionPermission) && isset($actionPermission[$action]) && !empty($permissions = $actionPermission[$action]);
            }else{
                //代表是二维数组配置
                $condition = !empty($actionPermission) && isset($actionPermission[$serviceInfo->getServer()]) && !empty($actionPermission[$serviceInfo->getServer()]);
                $condition  = $condition && isset($actionPermission[$serviceInfo->getServer()][$action]) && !empty($permissions = $actionPermission[$serviceInfo->getServer()][$action]);
                //条件拼装完成
            }

            //@这里必须有配置方法权限，然后必须该方法判断权限已设置，并且该方法设置的权限不为空
            if($condition){
                //代表需要认证权限
                /** @var RpcRequest $RpcClient */
                $RpcClient = BeanFactory::getBean(RpcRequest::class);
                foreach ($permissions as $v){
                    //这里需要两个参数
                    $params['permission_value'] = $v;
                    $params['user_item_id'] = $request->getAttribute('uid');
                    $params['tenant'] = $request->getAttribute('tenant');

                    if(!$request->getAttribute('uid')){
                        throw new PermissionException('您尚未登录，请先登录');
                    }
                    /** @var RpcResult $result */
                    $result = $RpcClient->getServiceByServiceInfo('Common.'.config('service.service_name', 'Gateway').'.Permission.isUserHasPermission')->setParams($params)->query();
                    if($result->getCode() == 200 && isset($result->getData()['result']['state']) && $result->getData()['result']['state'] == true){
                        continue;
                    }else{
                        throw new PermissionException('您没有操作权限');
                    }
                }
            }
            //根据uid查询权限
        }

        // before request handle

        return $handler->handle($request);

        // after request handle
    }
}
